package com.yzg.cas;

import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author misterWei
 * @create 2020年05月24号:20点23分
 * @mailbox forcontinue@163.com
 */
@Slf4j(topic = "c.AtomicArray")
public class AtomicArray {

    public static void main(String[] args) {
        // 普通数组
        AtomicInt.demo(
                ()-> new int[5],
                (array) -> array.length,
                (array,index) -> array[index]++ ,
                (array) -> log.info("{}", Arrays.toString(array))
        );
      // 原子数组
        AtomicInt.demo(
                ()-> new AtomicIntegerArray(5),
                (array) -> array.length(),
                (array,index) -> array.incrementAndGet(index) ,
                (array) -> log.info("{}", array.toString())
        );
    }

    interface AtomicInt{
        static  <T extends Object> void demo(
                Supplier<T> supplier,
                Function<T, Integer> function,
                BiConsumer<T, Integer> biConsumer,
                Consumer<T> consumer
        ){


            LinkedList<Thread> linkedList = new LinkedList();
            //获取到值
            T array = supplier.get();
            //得到数据的长度
            Integer length = function.apply(array);
            //测试这个数组长度的并发量
            CyclicBarrier cyclicBarrier = new CyclicBarrier(length);
            for (int i = 0; i < length; i++) {
                int index = i;
                Thread thread = new Thread(() -> {
                    try {
                        //模拟并发
                        cyclicBarrier.await();
                        for (int i1 = 0; i1 < 10000; i1++) {
                            //操作 每个线程都对其数组下标轮询递增
                            int i2 = i1%length;

                           biConsumer.accept(array,i2);
                        }
                    } catch (InterruptedException | BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }, i + " thread");
                linkedList.addLast(thread);
            }
            linkedList.forEach(thread -> {
                thread.start();
            });
            linkedList.forEach(thread -> {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            //输出结果
            consumer.accept(array);

        }
    }
}
